/* Umprogrammierte Version 2.0 mit folgenden Verbesserungen: - Im Programmirmodus blinkt die Zeiteinheit, die grade programmiert wird - KlickButton-Library zum Einlesen der Buttons - Sollte die Backup-Batterie leer sein, wird Zeit voreingestellt und in SET gesprungen - Sollte RTC nicht erkannt werden wir in Fehlermodus gesprungen - Umstieg auf RTCLib von Adafruit Zuletzt modifiziert: 01.11.17 Zuletzt hochgeladen: 05.11.2018 Status: Funktioniert */ #include #include "RTClib.h" // RTClib in Version 1.2.0 // RTC-Instanz initialisieren RTC_DS3231 realTimeClock; #include // FastLED in Version 3.1.6 #include "ClickButton.h" // ClickButton in Version 1.0.0 #include // elapsedMillis in Version 1.0.4 // Definitionen fuer den RGB Streifen (WS2813 RGB Strip, 60 LEDs/m. Gekauft bei led-stuebchen.de #define LED_PIN 5 #define NUM_LEDS 34 #define LED_TYPE WS2813 #define COLOR_ORDER GRB #define TASTER_PLUS 4 #define TASTER_MENU 3 #define TASTER_MINUS 2 #define MAX_BRIGHTNESS 100 // Thats full on, watch the power! #define MIN_BRIGHTNESS 0 // set to a minimum of 25% const int brightnessInPin = A0; CRGB leds[NUM_LEDS]; #define UPDATES_PER_SECOND 100 #define FARBE_STUNDEN Crimson #define FARBE_ZEHNERMINUTEN LimeGreen #define FARBE_MINUTEN Yellow // Taster einbinden ClickButton TasterMenu (TASTER_MENU, LOW, CLICKBTN_PULLUP); ClickButton TasterPlus (TASTER_PLUS, LOW, CLICKBTN_PULLUP); ClickButton TasterMinus (TASTER_MINUS, LOW, CLICKBTN_PULLUP); #define EINZELKLICK 1 #define DOPPELKLICK 2 #define LANGERKLICK -1 elapsedMillis IntervallSensorLesen; elapsedMillis ZeitAnzeigenIntervall; // elapsedMillis regularClear; // Strip loschen, damit Ueberlaufe richtig angezeigt werden elapsedMillis blinkenStunden; // Funktion, um LEDs im SET-Modus zu blinken elapsedMillis blinkenZehnerminuten; // Funktion, um LEDs im SET-Modus zu blinken elapsedMillis blinkenEinerminuten; // Funktion, um LEDs im SET-Modus zu blinken bool ERRORFLAG = false; // State-Machine Funktions-Namen typedef enum { HOCHFAHREN, ANZEIGE_ZEIT, EINSTELLEN_ZEIT, FEHLER } modus; modus Funktion = HOCHFAHREN; // Startfunktion der State-Machine // State-Machine RTC-Stellmodus typedef enum { STUNDEN, ZEHNERMINUTEN, EINERMINUTEN } set_modus; set_modus Funktion_Set = STUNDEN; // Startfunktion der SET Funktion void setup() { //Serial.begin(9600); // Initialisierung der LEDs FastLED.addLeds(leds, NUM_LEDS).setCorrection( TypicalLEDStrip ); FastLED.setBrightness(MAX_BRIGHTNESS); //realTimeClock.adjust(DateTime(2014, 1, 21, 11, 40, 55)); } void loop() { int mappedValue = map(analogRead(brightnessInPin), 0, 1023, 0, 100); FastLED.setBrightness(constrain(mappedValue, MIN_BRIGHTNESS, MAX_BRIGHTNESS)); if (ERRORFLAG == true) { Funktion = FEHLER; } // Taser lesen und Wert abspeichern TasterMinus.Update(); int taster_minus = TasterMinus.clicks; TasterMenu.Update(); int taster_menu = TasterMenu.clicks; TasterPlus.Update(); int taster_plus = TasterPlus.clicks; switch (Funktion) { case HOCHFAHREN: { // Hier werden Initialisierungen durchgefuhrt // Wenn RTC nicht erkannt wird: I2C-Problem. In den Fehlermodus springen if (!realTimeClock.begin()) { Funktion = FEHLER; } // Wenn RTC-Backup-Batterie gewechselt wurde, Zeit voreinstellen und in SET springen. 01.01.2017 07:08:09Uhr else if (realTimeClock.lostPower()) { realTimeClock.adjust(DateTime(2000, 1, 1, 12, 55, 0)); Funktion = EINSTELLEN_ZEIT; } else { ClearStrip(); Funktion = ANZEIGE_ZEIT; } } // Ende HOCHFAHREN break; case ANZEIGE_ZEIT: { ZeigeZeit(); if (taster_menu == LANGERKLICK) { ClearStrip(); Funktion = EINSTELLEN_ZEIT; } } // Ende ANZEIGE_ZEIT break; case EINSTELLEN_ZEIT: { static bool set_fertig = false; static int jahr_fest = 2017; static int monat_fest = 1; static int tag_fest = 1; static int stundenuebergabe = 0; static int zehnerminutenuebergabe = 0; static int einerminutenuebergabe = 0; if (set_fertig == false) // Wenn "frisch" in SET gesprungen wird, wird die aktuelle Zeit eingelesen. { DateTime now = realTimeClock.now(); stundenuebergabe = now.hour(); zehnerminutenuebergabe = (now.minute() / 10) % 10; // Zehnerminuten berechnen einerminutenuebergabe = (now.minute() % 10); // Einerminuten berechnen set_fertig = true; } switch (Funktion_Set) { case STUNDEN: { if (taster_minus == EINZELKLICK) { stundenuebergabe--; if (stundenuebergabe > 23) stundenuebergabe = 0; else if (stundenuebergabe < 0) stundenuebergabe = 23; } if (taster_plus == EINZELKLICK) { stundenuebergabe++; if (stundenuebergabe > 23) stundenuebergabe = 0; else if (stundenuebergabe < 0) stundenuebergabe = 23; } if (taster_menu == EINZELKLICK) { Funktion_Set = ZEHNERMINUTEN; } AnzeigeStundenBlinkend(stundenuebergabe); //AnzeigeZehnerminuten(zehnerminutenuebergabe); //AnzeigeEinerminuten(einerminutenuebergabe); } // Ende STUNDEN break; case ZEHNERMINUTEN: { if (taster_minus == EINZELKLICK) { zehnerminutenuebergabe--; if (zehnerminutenuebergabe > 5) zehnerminutenuebergabe = 0; else if (zehnerminutenuebergabe < 0) zehnerminutenuebergabe = 5; } if (taster_plus == EINZELKLICK) { zehnerminutenuebergabe++; if (zehnerminutenuebergabe > 5) zehnerminutenuebergabe = 0; else if (zehnerminutenuebergabe < 0) zehnerminutenuebergabe = 5; } if (taster_menu == EINZELKLICK) { Funktion_Set = EINERMINUTEN; } AnzeigeZehnerminutenBlinkend(zehnerminutenuebergabe); } // Ende ZEHNERMINUTEN break; case EINERMINUTEN: { if (taster_minus == EINZELKLICK) { einerminutenuebergabe--; if (einerminutenuebergabe > 9) einerminutenuebergabe = 0; else if (einerminutenuebergabe < 0) einerminutenuebergabe = 9; } if (taster_plus == EINZELKLICK) { einerminutenuebergabe++; if (einerminutenuebergabe > 9) einerminutenuebergabe = 0; else if (einerminutenuebergabe < 0) einerminutenuebergabe = 9; } if (taster_menu == EINZELKLICK) { Funktion_Set = STUNDEN; } AnzeigeEinerminutenBlinkend(einerminutenuebergabe); } // Ende EINERMINUTEN break; } if (taster_menu == LANGERKLICK) { realTimeClock.adjust(DateTime(jahr_fest, monat_fest, tag_fest, stundenuebergabe, (einerminutenuebergabe + (zehnerminutenuebergabe * 10)), 0)); set_fertig = false; Funktion_Set = STUNDEN; ClearStrip(); ZeigeZeit(); Funktion = ANZEIGE_ZEIT; } } // Ende EINSTELLEN_ZEIT break; case FEHLER: { // bei Fehlern gesamten LED Strip rot blinken leds[0] = CRGB::Red; leds[NUM_LEDS - 1] = CRGB::Red; FastLED.show(); while (1); } // Ende FEHLER break; } } int ZeigeZeit() { DateTime now = realTimeClock.now(); //Aktuelle Zeit aus der RTC holen und in "now" zwischenspeichern AnzeigeStunden(now.hour()); AnzeigeZehnerminuten ((now.minute() / 10) % 10); AnzeigeEinerminuten (now.minute() % 10); ZeitAnzeigenIntervall = 0; } void ClearStrip() { // Alle LEDs in einer fliessenden Bewegung von rechts nach links loeschen (Black) for (int i = 0; i <= NUM_LEDS - 1; i++) { leds[i] = CRGB::Black; FastLED.show(); } } int AnzeigeStunden (int wert) { // Funktion, um die Stunden anzuzeigen. 24h wird in 12h "runtergebrochen" if (wert > 12) wert = (wert - 12); else if (wert > 23) wert = 0; int werte_led_tabelle[12][2] = { // Umrechnungstabelle. {1, 19} heisst = alle LEDs bis 19 leuchten, {5, 24} alle LEDs bis 24 leuchten //(STUNDE, LED-NR im Strip) {1, 19}, {2, 20}, {3, 21}, //Sprung, eine LED zwischendrin frei (Nr 22) {4, 23}, {5, 24}, {6, 25}, //Sprung, eine LED zwischendrin frei (Nr 26) {7, 27}, {8, 28}, {9, 29}, //Sprung, eine LED zwischendrin frei (Nr 30) {10, 31}, {11, 32}, {12, 33} }; for (int i = 0; i <= wert - 1; i++) { leds[(werte_led_tabelle[i][1])] = CRGB::FARBE_STUNDEN; FastLED.show(); } for (int f = wert; f <= 11; f++) { leds[(werte_led_tabelle[f][1])].fadeToBlackBy(255); FastLED.delay(10); FastLED.show(); } } void AnzeigeStundenBlinkend(int stunden) { if (blinkenStunden > 350) { static bool lastMode = 0; if (lastMode == 0) { AnzeigeStunden(stunden); lastMode = 1; } else { ClearStrip(); lastMode = 0; } blinkenStunden = 0; } } int AnzeigeZehnerminuten (int wert) { // Funktion, um die Zehnerminuten anzuzeigen. if (wert > 5 || wert < 0) { wert = 0; } int werte_led_tabelle[5][2] = { {1, 17}, {2, 16}, {3, 15}, //Sprung, eine LED zwischendrin frei {4, 13}, {5, 12} }; for (int j = 0; j <= wert - 1; j++) { leds[(werte_led_tabelle[j][1])] = CRGB::FARBE_ZEHNERMINUTEN; FastLED.show(); } for (int g = wert; g <= 4; g++) { leds[(werte_led_tabelle[g][1])].fadeToBlackBy(255); FastLED.delay(10); FastLED.show(); } } void AnzeigeZehnerminutenBlinkend(int wert) { if (blinkenZehnerminuten > 350) { static bool lastMode = 0; if (lastMode == 0) { AnzeigeZehnerminuten(wert); lastMode = 1; } else { ClearStrip(); lastMode = 0; } blinkenZehnerminuten = 0; } } int AnzeigeEinerminuten (int wert) { // // Funktion, um die Einerminuten anzuzeigen. LEDs 0 - 10 von links if (wert > 9 || wert < 0) { wert = 0; } int werte_led_tabelle[9][2] = { {1, 10}, {2, 9}, {3, 8}, //Sprung, eine LED zwischendrin frei {4, 6}, {5, 5}, {6, 4}, //Sprung, eine LED zwischendrin frei {7, 2}, {8, 1}, {9, 0} // erste LED im Streifen = LED 0, weil Array bei 0 beginnt }; for (int k = 0; k <= wert - 1; k++) { leds[(werte_led_tabelle[k][1])] = CRGB::FARBE_MINUTEN; FastLED.show(); } for (int m = wert; m <= 8; m++) { leds[(werte_led_tabelle[m][1])].fadeToBlackBy(255); FastLED.delay(10); FastLED.show(); } } void AnzeigeEinerminutenBlinkend(int wert) { if (blinkenEinerminuten > 350) { static bool lastMode = 0; if (lastMode == 0) { AnzeigeEinerminuten(wert); lastMode = 1; } else { ClearStrip(); lastMode = 0; } blinkenEinerminuten = 0; } }